把Fortunes跟練習專案交叉測試了
確認不是.net core 2.0的問題,所以1.1版的Service registry和discovery可以正常使用
接著Day19的後續,開始改APIGateway專案,
appsettings.json中加入 eureka的設定
"eureka": {
"client": {
"serviceUrl": "http://localhost:8761/eureka/",
"shouldRegisterWithEureka": false
}
}
接著在Startup.cs的Startup方法中加入下面的設定(由於我們在ConfigServer的時候已經加入相關設定, 如果重頭寫寫的時候沒有加入AddJsonFile是沒有辦法讀到appsettings.json)
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables()
.AddConfigServer();
Configuration = builder.Build();
}
在ConfigureServices裡面加入了AddDiscoveryClient, 同時為後面要調用的IProductService設定singleton注入
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddOptions();
services.AddDiscoveryClient(Configuration);
services.AddSingleton<IProductService, ProductService>();
services.Configure<ConfigServerData>(Configuration);
services.AddMvc();
}
Program.cs 維持原狀(其實這邊設定有誤造成service discovery無法解析名字,此地雷後述~)
切換到ProdcutService專案裡面controller 看一下有哪些API ,等等要在APIGateway專案裡調用
namespace ProductService.Controllers
{
[Route("api/[controller]")]
public class ProductController : Controller
{
// GET api/values
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "Product1", "Product2" };
}
// GET api/values/5
[HttpGet("{id}")]
public string Get(int id)
{
return "Product"+id;
}
}
}
在APIGateway專案新增一個Service資料夾 增加IProductService定義需要調用的ProductService介面
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace APIGateway.Services
{
public interface IProductService
{
string GetValue(int id);
string[] GetValues();
}
}
增加ProductService 實作IProduceService規定的方法, service discovery會在這邊注入使用,
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Pivotal.Discovery.Client;
using System.Collections.Generic;
using System.Net.Http;
namespace APIGateway.Services
{
public class ProductService : IProductService
{
DiscoveryHttpClientHandler _handler;
private const string ProductServiceAPI_URL = "http://ProductService/api/values";
public ProductService(IDiscoveryClient client, ILoggerFactory logFactory) {
_handler = new DiscoveryHttpClientHandler(client);
}
public string GetValue(int id) {
var client = new HttpClient(_handler, false);
var result = client.GetStringAsync($"{ProductServiceAPI_URL}/{id}").Result;
return result;
}
public string[] GetValues() {
var client = new HttpClient(_handler, false);
var response = client.GetAsync(ProductServiceAPI_URL).Result;
var responseBody = response.Content.ReadAsStringAsync().Result;
var result = JsonConvert.DeserializeObject<List<string>>(responseBody);
return result.ToArray();
}
}
}
到APIGateway對應的controller下調用IProductService
using System.Collections.Generic;
using APIGateway.Services;
using Microsoft.AspNetCore.Mvc;
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
namespace APIGateway
{
[Route("api/[controller]")]
public class ProductController : Controller
{
// GET: api/values
public ProductController(IProductService service) {
_productService = service;
}
IProductService _productService;
[HttpGet]
public IEnumerable<string> Get() {
return _productService.GetValues();
}
// GET api/values/5
[HttpGet("{id}")]
public string Get(int id) {
return _productService.GetValue(id);
}
}
}
到這邊應該就完成了
執行後會發現HttpClient那邊會拋出錯誤,但是會發現交叉比對之下FortuneService-Teller-UI跟APIGateway都無法解析ProductService在Eureka對應的資源名稱,結果是HttpClient發request時找不到伺服器,
最後發現是Program.cs裡面啟動程式的位址寫法對service discovery有影響,注意這兩行
.UseUrls("http://*:1234")
//.UseUrls("http://localhost:1234") // service discovery can't work
這兩個設定程式都能跑 而且都會在localhost:1234啟動,在Eureka也可以註冊,
但是第二行的service discovery是無法找到服務的位置的,我在官方文件沒看到說明,可能要看source code或是發issue問一下了....
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseUrls("http://*:1234")
//.UseUrls("http://localhost:1234") // service discovery can't work
.Build();
}
短短一行 幾個小時就掰了..............